<?php 

class ocorrencia_grupoModel extends CatModel{
    
    public    $tabela            = "ocorrencia_grupo";
    public    $pkey              = 'cod_grupo';
    protected $model_label       = "Grupos de Trabalho";
    protected $model_description = "Os grupos de trabalho permitem organizar os assuntos semelhantes em um mesmo local.
        Os usuários que pertencem a um grupo podem criar novos assuntos, subgrupos e gerenciar os subgrupos criados.";
    
    //dados especificos da categoria
    protected $categorized_model = "ocorrencia/ocorrencias";
    protected $multinivel_model  = "";
    protected $nome_cod          = "cod_grupo";
    protected $nome_cat          = "nome";
    protected $nome_pai          = "cod_pai";
    protected $dados = array(
        'button' => array(
            'button'    => "Salvar Grupo",
        ),
        
        /*'ocorrencia_tarefa' => array(
            'name'      => 'Tarefas',
            'private'   => true,
            'fkey'      => array(
                'model' 	=> 'ocorrencia/tarefa',
                'keys'          => array('ocorrencia_grupo_cod', 'ocorrencia_grupo_cod'),
                'cardinalidade' => 'n1'//nn 1n 11
            )
         ),*/
        
        'ocorrencia_ocorrencias' => array(
            'name'          => 'Assuntos',
            //'private'       => true,    
            'especial'      => 'hide',
            'display'       => true,
            'display_in'    => 'table',
            'fkey'      => array(
                'sort'          => 'atualizacao DESC',
                'limit'         => 10,
                'model' 	=> 'ocorrencia/ocorrencias',
                'keys'          => array('grupo', 'grupo'),
                'cardinalidade' => 'n1'//nn 1n 11
            )
         ),
                
        'participantes' => array(
	    'name'    => 'Participantes',
	    'type'    => 'int',
	    'display' => true,
	    'fkey'    => array(
                'cardinalidade' => 'nn',
	        'model'         => 'ocorrencia/pertence',
	        'keys'          => array('cod_usuario', 'user_name', 'user_cargo'),
                'sort'          => 'user_name ASC',
                'formmodel'     => 'ocorrencia/grupo',
                'onupdate'      => 'cascade',
                'ondelete'      => 'cascade'
	    )
         ),
        
        'g_status' => array(
            'name' 	=> 'Status',
            'type' 	=> 'enum',
            'default' 	=> 'ativo',
            'private'   => true,
            'options'   => array(
                'ativo'     => 'Ativo',
                'arquivado' => 'Arquivado'
            ),
            'notnull'   => true,
        ),
        
        'g_descricao' => array(
            'name' 	=> 'Descrição',
            'type' 	=> 'varchar',
            'size' 	=> '256',
            //'display'   => true,
            //'notnull'   => true,
            //'especial'  => 'editor',
            //'editor'    => array('format', 'list', 'link', 'history'),
        ),
    );
    public function __construct() {
        parent::__construct();
        $this->LoadModel('usuario/login', 'uobj');
        $this->LoadModel('ocorrencia/ocorrencias', 'oc');
        $this->LoadModel('ocorrencia/pertence', 'pmd');
        $this->cod_usuario = $this->uobj->getCodUsuario();
        $this->allgroups = $this->getAllGroups();
        $this->dados[$this->nome_pai]['especial'] = 'hide';
    }
    
    public function getAllGroups(){
        
        $where = "g_status = 'ativo'";
        if(cookie::cookieExists('allgroups')){
            $last  = $this->getLastId();
            $allg  = cookie::getVar('allgroups');
            $total = $this->getCount($where);
            if($allg['last'] == $last && $allg['total'] == $total && !empty ($allg['grupo'])){
                $this->db->clearJoin();
                return $allg['grupo'];
            }
        }
        
        $allg['grupo'] = $this->selecionar(array(), $where, "", "", "$this->nome_cat ASC");
        $allg['last']  = $this->getLastId();
        $allg['total'] = $this->getCount($where);
        cookie::setVar('allgroups', $allg);
        return $allg['grupo'];
    }

    /*
     * recupera dos dados de um formulário de participantes
     */
    public function getParticipantesForm(){
        return $this->pmd->getDados();
    }
    
    /*
     * recupera todos os participantes de um grupo
     */
    public function getParticipantes($grupo){
        $tabela = $this->pmd->getTable();
        $tusuarios = $this->uobj->getTable();
        $this->db->Join($tabela, $this->tabela);
        $this->db->Join($tabela, $tusuarios);
        $var = $this->pmd->selecionar(
                    array('cod_usuario','user_name','user_cargo'),
                   "cod_grupo = '$grupo'", "", "", "user_name ASC"
        );
        //echo $this->db->getSentenca();
        return $var;
    }
    
    /*
     * Remove um participante de um grupo
     */
    public function removerParticipante($dados){
        if(empty ($dados)) return;
        $var[] = $dados['cod_usuario'];
        $var[] = $dados['cod_grupo'];
        if(!$this->pmd->apagar($var, array('cod_usuario', 'cod_grupo'))){
            $this->setErrorMessage($this->pmd->getErrorMessage());
            return false;
        }
        $this->setSuccessMessage(REMOVER_USUARIO_DE_UM_GRUPO);
        return true;
    }
    
    public function getSuperiores($cod_grupo){
        static $list = array();
        if(empty ($list)){
            $list = array("0" => '');
            foreach($this->allgroups as $t){
                $list[$t['cod_grupo']] = ($t['cod_pai'] != "")?$t['cod_pai']:"0";
            }
        }
        
        $superiores = array();
        $pai = isset($list[$cod_grupo])?$list[$cod_grupo]:"";
        while($pai != ""){
            $superiores[] = $pai;
            $pai = $list[$pai];
        }
        return($superiores);
    }
        
    public function getSubordinados($cod_grupo){
        
        static $subordinados_cache = array();
        if(array_key_exists($cod_grupo, $subordinados_cache))
                return $subordinados_cache[$cod_grupo];
        
        foreach($this->allgroups as $t){
            $list[($t['cod_pai'] == "")?"0":$t['cod_pai']][] = $t['cod_grupo'];
        }
        
        $subordinados = $netos = array();
        if(!array_key_exists($cod_grupo, $list)) return array();
        $filhos = $list[$cod_grupo];
        while(!empty ($filhos)){
            $filho = array_shift($filhos);
            if(array_key_exists($filho, $list)) {
                if(!empty ($list[$filho]))
                    $netos[] = $list[$filho];
            }
            $subordinados[] = $filho;
            if(empty ($filhos)) $filhos = array_shift($netos);
        }
        $subordinados_cache[$cod_grupo] = $subordinados;
        return($subordinados);
    }
    
    public function getListOfAccess($cod_usuario = ""){
        static $listof = array();
        if(!empty ($listof)) return $listof;
        
        $var = $this->getPertenceList($cod_usuario);
        //procura os grupos subordinados
        $out = array();
        foreach($var as $v){
            $temp = $this->getSubordinados($v['cod_grupo']);
            if(!empty($temp))
                foreach ($temp  as $t) 
                    $out[$t] = $t;
            $out[$v['cod_grupo']] = $v['cod_grupo'];
        }
        
        $listof = $out;
        return $out;
    }
    
    /*
     * retorna uma lista de todos os grupos nos quais o usuário é 
     * superior hierárquico ou que ele pertence (ou seja, todos que ele tem acesso)
     */
    public function getListOfSubordinados($cod_usuario = ""){
        static $listof = array();
        if(!empty ($listof)) return $listof;
        $var = $this->getPertenceList($cod_usuario);
        //procura os grupos subordinados
        $out = array();
        foreach($var as $v){
            $temp = $this->getSubordinados($v['cod_grupo']);
            $out = array_merge($temp, $out);
            $out[] = $v['cod_grupo'];
        }
        $listof = $out;
        return $listof;
    }
    
    //seleciona os grupos nos quais o usuário pertence
    public function getPertenceList($cod_usuario = ""){
        static $pertencelist = array();
        if(!empty ($pertencelist)) return $pertencelist;
        
        $tb = $this->pmd->getTable();
        $this->db->Join($this->tabela, "$tb as user", array("cod_grupo"), array('cod_grupo'), "LEFT");
        $cod = $this->cod_usuario;
        if($cod_usuario != ""){
            if($cod != $cod_usuario){
                $this->db->Join($this->tabela, "$tb as otheruser", 
                        array("cod_grupo"), 
                        array('cod_grupo'), 
                        "LEFT");
                $where = "user.cod_usuario = '$cod_usuario' and otheruser.cod_usuario='$cod'";
                //$where = "cod_usuario = '$cod_usuario'";
            }
            else $where = "cod_usuario = '$cod'";
        }else $where = "cod_usuario = '$cod'";
        $pertencelist = parent::selecionar(array('user.cod_grupo', 'nome', 'cod_pai'), $where);
        return $pertencelist;
    }

    
    /*
     * retorna todos os grupos que o usuário tem acesso
     */
    public function getGroups($cod_usuario = "", $where = "", $allgroups = true){
        
        static $groups = array();
        $save = ($cod_usuario == "")?true:false;
        $enc = base64_encode($where);
        if($save && !empty ($groups[$enc])) {return $groups[$enc];}
        $cod_usuario = ($cod_usuario == "")?$this->cod_usuario:$cod_usuario;
        
        $wh = "";
        if(!$this->uobj->UserIsAdmin()){
            $out = $this->getListOfAccess($cod_usuario);
            if(empty ($out)) return array();
            $wh  = " AND cod_grupo IN(".  implode(",", $out).")";
        }
        
        $where  = trim("$where $wh");
        $campos = $this->getCampos();
        $var = parent::selecionar($campos, $where);
        if(empty ($var)) return $var;
        
        $virg = "";
        $list = "grupo IN(";
        foreach($var as $v){
            if(empty ($v)) continue;
            $var2[$v['cod_grupo']] = $v;
            $list .= $virg. $v['cod_grupo'];
            $virg = ", ";
        }
        $list .= ") ";
        /*$oc = $this->oc->selecionar(
            array('grupo', 'cod_ocorrencia', 'assunto', 'descricao', 'criadoem'), 
            $list . ' GROUP BY grupo', "", "", 'criadoem DESC'
        );
        foreach($oc as $o) $var2[$o['grupo']]['ocorrencia_ocorrencias'][$o['cod_ocorrencia']] = $o;
         * 
         */
        if($save) {$groups[$enc] = $var2;}
        return $var2;
    }
    
    public function getLevelGroup($cod_pai = ''){
        $wh = $where = "";
        if(!$this->uobj->UserIsAdmin()){
            $out = $this->getListOfSubordinados();
            if(empty($out)) return $out;
            $wh = "AND cod_grupo IN(".  implode(", ", $out).") ";
            $where  = ($cod_pai != "")? " AND cod_pai = '$cod_pai' ":"";
        }else $where  = ($cod_pai != "")? " AND cod_pai = '$cod_pai' ":" AND ISNULL(cod_pai)";
        
        
        
        $arr = $this->getCampos();
        $var = $this->selecionar($arr, "g_status = 'ativo' $where $wh");
        //echo $this->db->getSentenca(); print_r($var); die();
        return $var;
    }
       
    //recupera a lista de permissões dos grupos que um usuário tem permissão
    private function getAssociado(&$vout, &$perm){
        $vout = $perm = array();
        $cod_usuario = $this->cod_usuario;
        $tb = $this->pmd->getTable();
        $this->db->Join($tb, $this->tabela);
        $var = $this->pmd->selecionar(
                array('cod_grupo', 'nome', 'cod_pai'), 
                "cod_usuario = '$cod_usuario'", "", "", 
                "cod_pai, cod_grupo ASC"
        );
        
        if(empty ($var)) return;
        foreach($var as $a){
            $perm[] = $a['cod_grupo'];
        }
        
        $var = $this->allgroups;
        foreach($var as $a ){
            $vout[$a['cod_grupo']] = $a['nome'];
        }
    }
    
    /*
     * retorna um array com dados associados que mostram os filhos de um pai
     */
    public function getMenuAssoc(){
        static $save = array();
        if(!empty ($save)) return $save; 
        $all  = $this->allgroups;
        
        $arr = array();
        foreach($all as $a){
            if($a['cod_pai'] == "") $a['cod_pai'] = 0;
            $arr[$a['cod_pai']][$a['cod_grupo']] = $a['nome'];
        }
        $save = $arr;
        return $arr;
    }
    
    public function geraMenu($cod_cat = 0, $niveis = 20, $where = ""){
        $where = "g_status = 'ativo'";
        if($this->uobj->UserIsAdmin()) return parent::geraMenu($cod_cat, $niveis, $where);
        
        $this->getAssociado($vout, $permissoes);
        $menu_assoc = $this->getMenuAssoc();
        $out = array();
        
        $v = $this->PermissaoHierarquica($menu_assoc, $permissoes);
        $this->geraMenuPermissoes($v, $menu_assoc, $vout, $out, $niveis);
        return $out;
    }
    
    private function PermissaoHierarquica($menu_assoc, $perm){
        
        if(!function_exists('checa')){
            function checa($in, $perm, &$out, $i = 0){
                if(empty ($in)) return;
                if(in_array($i, $perm)){
                    $out[$i] = $in;
                    return;
                }

                if(!array_key_exists($i, $in)) return;
                if(!is_array($in[$i])) return;
                foreach($in[$i] as $c => $a){
                    if(in_array($c, $perm)) $out[$c] = $a;
                    else checa($in[$i], $perm, $out, $c);
                }
            }
        }
        $out = array();
        $this->GeraHierarquia($menu_assoc, $out);
        $o = array();
        checa($out, $perm, $o);
        return $o;
    }
    
    private function geraMenuPermissoes($hierarquia, $menuTotal, $vout, &$out, $niveis = 0){
        static $nivel = 0;
        foreach($hierarquia as $cod => $arr){
            if(!is_array($arr)){
                $link = "$this->link/show/$arr/".  GetPlainName($vout[$arr]);
                $out[$vout[$cod]][$vout[$arr]] = $link;
            }else{
                $link = "$this->link/show/$cod/".  GetPlainName($vout[$cod]);
                $out[$vout[$cod]][$vout[$cod]] = $link;
            }
            if(is_array($arr) && ($niveis == 0 || $niveis > ($nivel + 1))  ) {
                $nivel++;
                $this->geraMenuPermissoes ($hierarquia[$cod], $menuTotal, $vout, $out[$vout[$cod]], $niveis);
            }
        }
    }
    
    /*
     * Gera a hieraquia de grupos de trabalho
     */
    public function GeraHierarquia($menu_assoc, &$out, $cod = 0){
        if(!isset($menu_assoc[$cod])) return;
        foreach($menu_assoc[$cod] as $c => $a){
            if(!array_key_exists($c, $menu_assoc)){
                $out[$cod][$c] = $c;
            }else{
                if(!isset($out[$cod])) $out[$cod] = array();
                $this->GeraHierarquia($menu_assoc, $out[$cod], $c);
            }
        }
    }
    
    public function CheckPermissao($cod_grupo){
        
        //usuário admin pode tudo!
        if($this->uobj->UserIsAdmin())return true;
        
        $this->getAssociado($vout, $perm);
        //print_r($perm); die("<br/>$cod_grupo");
        //se existe no array simples de permissoes então retorna
        if(in_array($cod_grupo, $perm)) return true;
        
        //se não existe no array de itens então grupo não existe
        if(!array_key_exists($cod_grupo, $vout)) return false;
        
        $out = array();
        $arr = $this->getMenuAssoc();
        $this->GeraHierarquia($arr, $out);
        
    }
       
    //ocorrencias a serem exibidas na página inicial do grupo...
    public function getOcorrenciasByGroup($cod_grupo, $filter, $qtd = 12){
        $page = 0;
        $this->oc->filter($filter);
        return $this->getTodasOcorrencias($page, 12, $filter);
    }
    
    public function getLevelOcorrencias($grupos, $page, $qtd = 10){
        if(empty($grupos)) return array();
        $temp = array();
        foreach($grupos as $gr) $temp[] = $gr['cod_grupo'];
        $g = implode(', ', $temp);
        $where = "cod_grupo IN ($g)";
        $this->oc->setOrder("$this->tabela.nome ASC, atualizacao DESC");
        return $this->oc->paginate($page, 'ocorrencia/grupo/sub', "", "", $qtd, array(), $where);
    }
    
    public function getEmAtraso($cod, $page, $qtd = 10){
        $where = "(previsao_encerramento < NOW() AND previsao_encerramento != NULL)";
        $this->oc->filter(array('andamento', 'paralisado'));
        $this->oc->addWhere($where);
        $link = "ocorrencia/grupo/filter/$cod/atraso";
        $var[EM_ATRASO]['link']  = $link;
        $var[EM_ATRASO]['item']  = $this->oc->paginate($page, $link, "", "", $qtd);
        $var[EM_ATRASO]['count'] = $this->oc->getPaginateCount();  
        //echo $this->db->getSentenca();
        $this->LoadResource('html/paginator', 'pag');
        $name = GetPlainName(EM_ATRASO);
        $temp = $this->pag->draw(false);
        EventTube::addEvent($name, $temp);
        return $var; 
    }
    
    public function getMinhasSolicitacoes($cod, $page, $qtd = 10){
        $where = "criado_por = '$this->cod_usuario' AND (previsao_encerramento > NOW() OR previsao_encerramento = '0000-00-00')";
        $this->oc->filter(array('andamento', 'paralisado'));
        $this->oc->addWhere($where);
        $link = "ocorrencia/grupo/filter/$cod/solicitadas";
        $var[MINHAS_SOLICITACOES]['link']  = $link;
        $var[MINHAS_SOLICITACOES]['item']  = $this->oc->paginate($page, $link, "", "", $qtd);  
        $var[MINHAS_SOLICITACOES]['count'] = $this->oc->getPaginateCount();  
        $this->LoadResource('html/paginator', 'pag');
        $name = GetPlainName(MINHAS_SOLICITACOES);
        $temp = $this->pag->draw(false);
        EventTube::addEvent($name, $temp);
        return $var;
    }

    public function getTodasOcorrencias($cod, $page, $qtd = 10, $filther = array('andamento', 'paralisado')){
        $this->oc->filter($filther);
        //$this->oc->addWhere($where);
        $link = "ocorrencia/grupo/filter/$cod/todas";
        $var[TODAS_OCORRENCIAS]['link']  = $link;
        $var[TODAS_OCORRENCIAS]['item']  = $this->oc->paginate($page, $link, "", "", $qtd);  
        $var[TODAS_OCORRENCIAS]['count'] = $this->oc->getPaginateCount();  
        $this->LoadResource('html/paginator', 'pag');
        $name = GetPlainName(TODAS_OCORRENCIAS);
        $temp = $this->pag->draw(false);
        EventTube::addEvent($name, $temp);
        return $var;
    }
    
    public function getUltimasOcorrencias($cod, $page, $qtd = 10){
        $where = "criado_por != '$this->cod_usuario' AND (previsao_encerramento > NOW() OR previsao_encerramento = '0000-00-00')";
        $this->oc->filter(array('andamento', 'paralisado'));
        $this->oc->addWhere($where);
        $link = "ocorrencia/grupo/filter/$cod/ultimas";
        $var[ULTIMAS_OCORRENCIAS]['link']  = $link;
        $var[ULTIMAS_OCORRENCIAS]['item']  = $this->oc->paginate($page, $link, "", "", $qtd);  
        $var[ULTIMAS_OCORRENCIAS]['count'] = $this->oc->getPaginateCount();  
        $this->LoadResource('html/paginator', 'pag');
        $name = GetPlainName(ULTIMAS_OCORRENCIAS);
        $temp = $this->pag->draw(false);
        EventTube::addEvent($name, $temp);
        return $var;
    }
    
    public function arquivo($cod, $page, $qtd = 10){
        $this->oc->filter(array('cancelado', 'concluido'));
        $link = "ocorrencia/grupo/arquivo/$cod/";
        return $this->oc->paginate($page, $link, "", "", $qtd);  
    }
    
    public function lixeira($cod, $page, $qtd = 10){
        $this->oc->filter(array('excluido'));
        $link = "ocorrencia/grupo/lixeira/$cod/";
        return $this->oc->paginate($page, $link, "", "", $qtd);  
    }
   
    public function inserir($post){
        //print_r($post); die();
        return parent::inserir($post);
    }
    
    public function arquivar($cod_grupo, $status = ''){
        if($status == "")
             $post['g_status'] = $this->IsArquivado($cod_grupo)?'ativo': 'arquivado';
        else $post['g_status'] = $status;
        
        if($post['g_status'] == 'ativo'){
            $grupos = $this->selecionar(array($this->nome_pai), "$this->pkey = '$cod_grupo'");
            if(isset($grupos[0][$this->nome_pai])) $grupos[0] = $grupos[0]['cod_pai'];
            else unset($grupos);
        }elseif($post['g_status'] == "arquivado") $grupos = $this->getSubordinados($cod_grupo);
        
        if(isset($grupos)){
            foreach($grupos as $g)
                $this->arquivar($g, $post['g_status']);
        }
            
        $bool = parent::editar($cod_grupo, $post);
        if(!$bool){
            $this->setErrorMessage('Alterações no arquivamento do grupo não puderam ser concluídas');
            return false;
        }
        $this->setSuccessMessage("Alteração no grupo feita com sucesso!");
        return true;
    }
    
    public function IsArquivado($cod_grupo){
        $grupo = $this->selecionar(array('g_status'), "cod_grupo = '$cod_grupo'");
        if(empty($grupo)){
            $this->setErrorMessage("O grupo que você está tentando acessar não existe!");
            return false;
        }
        $grupo = array_shift($grupo);
        return ($grupo['g_status'] == 'arquivado');
    }
    
    public function checkGroupIsEmpty($cod_grupo){
        $total = $this->oc->getCount("grupo = '$cod_grupo'");
        if($total != 0) {
            $this->setErrorMessage('Este grupo possui Assuntos');
            return false;
        }
        
        $total = $this->getCount("cod_pai = '$cod_grupo'");
        if($total != 0) {
            $this->setErrorMessage('Este grupo possui subgrupos');
            return false;
        }
        return true;
    }
}
?>